/***************************************************************************************** 
*                                     TinyRtos51 
*                                The Real-Time Kernel 
*                              Copyright(c) 2024 fanxsp
*                         SPDX-License-Identifier: APACHE-2.0
*       This software is subject to an open source license and is distributed by fanxsp,
*       pursuant to the terms of the Apache License.
******************************************************************************************/
/******************************************************************************************* 
* 				main.c文件
* Author: fanxsp 
* Revision: 1.00
* Date: 2023-05-03
* 	1. 在tinyrtos51cfg.h 中配置 OS
*   2. 在port.h port_xxx.h中适配不同型号的 MCU
*   3. 在option的c51中的预定义宏中定义目标MCU型号
*   4. 如果使能定时服务，需要在一个定时器中调用OSTimeTick()函数，定时中断应设为最低优先级
********************************************************************************************/

/*************  功能说明    ****************************************************************
* 本例程基于STC8H8K64U核心实验板（开天斧）进行编写测试。
* 测试用消息队列进行串口通迅，串口波特率9600
*   按P32 P33 P34 P35 发送相应字串到串口助手
*   向实验板发送一个字节，控制LED，每位控制1个LED
* 下载时, 选择时钟 22.1184MHZ。
* 测试目的：二值信号量、消息队列
********************************************************************************************/
#include "tinyRtos51.h"
#include "Led.h"
#include "uart.h"


#define MAIN_Fosc       22118400L   
#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer0 中断频率 1000次/秒 周期为1ms

/* 任务定义 -------------------------------------------------------------------------------*/
/* 任务堆栈  */
OStypeInt8u OSLOC_STACKS TFLedStack[30] ;
OStypeInt8u OSLOC_STACKS TFKeyStack[30] ;
OStypeInt8u OSLOC_STACKS TFUart1TxStack[30] ;
/* 任务ID  */
#define ID_TFLed  0
#define ID_TFKey  1
#define ID_TFUart1Tx 2
/* 任务优先级 */
#define PRIO_TFLed  5
#define PRIO_TFKey  5
#define PRIO_TFUart1Tx 4
/* 任务函数原型 */
void TFLed(void) ;
void TFKey(void) ;
void TFUart1Tx(void) ;
/*-----------------------------------------------------------------------------------------*/


OStypeInt8u OSLOC_MSGQ_BUF Txbuf[50] ; // 串口发送队列缓存
OStypeInt8u OSLOC_MSGQ_BUF Rxbuf[50] ; // 串口接收队列缓存

unsigned char oldKey = 0;

#define KEY1	1
#define KEY2 	2
#define KEY3  3

void Init(void) ;
void Uart1_Init(void) ;
void PutString(unsigned char* s) ;

void main(void)
{
/* OS初始化  */
	OSInit() ;
	
/* 创建任务、二值信号量、计数信号量、事件标志、消息队列  放在这里 */
	OSCreateTask(ID_TFLed,TFLed,TFLedStack,PRIO_TFLed) ;
	OSCreateTask(ID_TFKey,TFKey,TFKeyStack,PRIO_TFKey) ;
	OSCreateTask(ID_TFUart1Tx,TFUart1Tx,TFUart1TxStack,PRIO_TFUart1Tx) ;
	
//	OSInitBinSem(ID_BINSEM_TXEND,0) ; // 设置二值信号量初值，为默认值0时，可以省略
	OSInitMsgQ(ID_MSGQ_TX,Txbuf,50) ;
	OSInitMsgQ(ID_MSGQ_RX,Rxbuf,50) ; // 初始化消息队列，消息队列使用前必须先初始化

/*----------------------------------------------------------------------------------------*/
	
/* 用户初始化 放在这里  */
	Init() ;
/*----------------------------------------------------------------------------------------*/
	
/* 启动OS */ 
	OSStart() ;
	
/* 后面不要放任何代码 */
	
}

/* 按键检测 任务 */
void TFKey(void)
{
	static unsigned char Key1Cnt;
	unsigned char newKey;
	
	for(;;)
	{
		
		if(!P64 || !P65 || !P66)
		{
			if(!P64) {
				newKey = KEY1;
			} else if (!P65) {
				newKey = KEY2;
			} else {
				newKey = KEY3;
			}
			
			if(oldKey != newKey) {
				Key1Cnt = 1;
				oldKey = newKey;
			}
			
			if(Key1Cnt < 0xff) Key1Cnt ++ ;
		}
		else
		{
			Key1Cnt = 0 ;
		}
		
		if(Key1Cnt == 2)
		{
			if(newKey == KEY1) {
				PutString("KEY1 is Pressed ......\r\n") ;
			} else if (newKey == KEY2) {
				PutString("KEY2 is Pressed ......\r\n") ;
			} else {
				PutString("KEY3 is Pressed ......\r\n") ;
			}
		}
		
		OSDelay(1) ;
	}
}

/* Uart1 数据发送任务 */
void TFUart1Tx(void)
{
	OStypeInt8u msg ;
	
	for(;;)
	{
		OSWaitMsgQ(ID_MSGQ_TX,&msg,0) ; // 判断队列中是否有消息，阻塞式等待
		SBUF = msg ;
		OSWaitBinSem(ID_BINSEM_TXEND,0) ; // 等待队列中的所有数据发送完成
	}
}

void ISR_Timer0(void) interrupt 1  // 1ms 中断函数
{
	
	OSTimeTick() ;    // OS节拍处理
}

void ISR_Uart1(void) interrupt 4  // UART1 中断
{
	OStypeInt8u msg ;
	
	if(TI)
	{
		TI = 0 ;
		// 判断发送消息队列中是否还有消息，如果有就放到串口发送缓冲寄存器中。如果没有了就发送一个二值信号量通知发送结束
		if(OSTryMsgQ(ID_MSGQ_TX,&msg)) {
			SBUF = msg ; // 发送队列非空 继续发送数据
		}
		else {
			OSIntSignalBinSem(ID_BINSEM_TXEND) ;   // 队列空 发送完成标志
		}
	}
	
	if(RI)
	{
		RI = 0 ;
		msg = SBUF ;
		OSIntSignalMsgQ(ID_MSGQ_RX,msg) ; // 将收到的数据发往消息队列
	}
}

void Init(void)
{
	P_SW2 |= 0x80;                //扩展寄存器(XFR)访问使能
	P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
	P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
	P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
	P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
	P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
	P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
	P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    
    led_init();
	
	Uart1_Init() ;
	
	AUXR |= 0x80;   //Timer0 1T, 16 bits 自动重装载模式 
	TH0 = (unsigned char)(Timer0_Reload / 256);
	TL0 = (unsigned char)(Timer0_Reload % 256);
	ET0 = 1;        //Timer0 中断使能
	TR0 = 1;        //Tiner0 开
}


